#ifndef __WIZ_REFCOUNT_HPP__SHANHAOBO_19800429__
#define __WIZ_REFCOUNT_HPP__SHANHAOBO_19800429__

#include "../../System/WizAtomicCount.hpp"
#include "../WizDataTypeAny.hpp"
#include "../WizDataTypePointer.hpp"

namespace Wiz
{
    /// reference counting
    namespace RefCount
    {
        template<class BaseType = ::Wiz::Null::Type>
        class SyncObj : public BaseType
        {
        protected:
            ::Wiz::AtomicCount::Ptr m_ACPtr;
        protected:
            SyncObj()
            {
                this->m_ACPtr = ::Wiz::AtomicCount::Create();
                WIZ_ASSERT(::Wiz::IsValidPtr(this->m_ACPtr));
            }
            virtual ~SyncObj()
            {
                ::Wiz::AtomicCount::Destroy(this->m_ACPtr);
                this->m_ACPtr = WIZ_NULLPTR;
            }
        public:
            ::Wiz::Void::Type AddRef()
            {
                this->m_ACPtr->Increment();
            }
            ::Wiz::Bool::Type Release()
            {
                if (this->m_ACPtr->DecIsZero())
                {
                    delete this;
                    return ::Wiz::Bool::True;
                }
                return ::Wiz::Bool::False;
            }
        public:
        };

        template<class BaseType = ::Wiz::Null::Type>
        class Object : public BaseType
        {
        protected:
            ::Wiz::Int::Type m_AC;
        protected:
            Object() : m_AC(0)
            {
            }
            virtual ~Object()
            {
                m_AC = 0;
            }
        public:
            ::Wiz::Void::Type AddRef()
            {
                this->m_AC++;
            }
            ::Wiz::Bool::Type Release()
            {
                WIZ_ASSERT(this->m_AC > 0);
                this->m_AC--;
                if (this->m_AC == 0)
                {
                    delete this;
                    return ::Wiz::Bool::True;
                }
                return ::Wiz::Bool::False;
            }
        public:
        };

        //////////////////////////////////////////////////////////////////////////
        class Type : public ::Wiz::RefCount::Object<>
        {
        private:
            ::Wiz::Any::Type m_Core;
        public:
            template<class T>
            Type(T t) : ::Wiz::RefCount::Object<>()
            {
                this->m_Core = t;
            }
            virtual ~Type()
            {

            }
        public:
            template<class T>
            T& Get()
            {
                return this->m_Core.Get<T>();
            }
        };
        WIZ_DECLARE(::Wiz::RefCount::Type);

        template<class T>
        WIZ_INLINE ::Wiz::RefCount::Ptr Create(T t)
        {
            return new ::Wiz::RefCount::Type(t);
        }
        //////////////////////////////////////////////////////////////////////////
    } /// end of namespace RefCount
} /// end of namespace Wiz

namespace Wiz
{
    namespace IntrusivePtr
    {
        template<class BaseT>
        ::Wiz::Void::Type AddRef(::Wiz::RefCount::SyncObj<BaseT>* MngdPtr)
        {
            MngdPtr->AddRef();
        }
        template<class BaseT>
        ::Wiz::Void::Type Release(::Wiz::RefCount::SyncObj<BaseT>* MngdPtr)
        {
            MngdPtr->Release();
        }
        template<class BaseT>
        ::Wiz::Void::Type AddRef(::Wiz::RefCount::Object<BaseT>* MngdPtr)
        {
            MngdPtr->AddRef();
        }
        template<class BaseT>
        ::Wiz::Void::Type Release(::Wiz::RefCount::Object<BaseT>* MngdPtr)
        {
            MngdPtr->Release();
        }
    } /// end of namespace IntrusivePtr
} /// end of namespace Wiz


#endif /*__WIZ_REFCOUNT_HPP__SHANHAOBO_19800429__*/
